﻿using System;
using System.Collections.Generic;
using Autodesk.Revit.DB;
using YJKArchUtils.Utils;
using YJKRevitDimensionText.OneKeyPlanDim.Utility;

namespace YJKRevitDimensionText.OneKeyPlanDim.DimesionDataEx
{
	public class WallDataEx
	{
		public ElementId WallId
		{
			get
			{
				return this.m_wallId;
			}
			set
			{
				this.m_wallId = value;
			}
		}

		public XYZ VecOutWall
		{
			get
			{
				return this.m_vec.Normalize();
			}
			set
			{
				this.m_vec = value;
			}
		}

		public bool IsOutWall
		{
			get
			{
				return this.m_bOutWall;
			}
		}

		public Curve ProfileLine
		{
			get
			{
				return this.m_profileLine;
			}
			set
			{
				this.m_profileLine = value;
			}
		}

		public Curve OutLine
		{
			get
			{
				this.AnalyzesWall();
				return this.m_outLine;
			}
			set
			{
				this.m_outLine = value;
			}
		}

		public Curve InLine
		{
			get
			{
				this.AnalyzesWall();
				return this.m_inLine;
			}
			set
			{
				this.m_inLine = value;
			}
		}

		public double WallWidth
		{
			get
			{
				XYZ xyz = (this.InLine.GetEndPoint(0) + this.InLine.GetEndPoint(1)) / 2.0;
				return this.OutLine.Distance(xyz);
			}
		}

		public List<DoorWinDataEx> WallWindows
		{
			get
			{
				return this.m_lstWallWindows;
			}
			set
			{
				this.m_lstWallWindows = value;
			}
		}

		public List<ElementId> ConnectWall
		{
			get
			{
				return this.m_lstConnectWall;
			}
			set
			{
				this.m_lstConnectWall = value;
			}
		}

		public WallDataEx(Wall wall, bool bOutWall, XYZ vec = null, Curve cvProfileLine = null)
		{
			this.m_Wall = wall;
			this.m_bOutWall = bOutWall;
			this.m_wallId = wall.Id;
			this.m_vec = vec;
			this.ProfileLine = cvProfileLine;
			if (!bOutWall && vec == null)
			{
				Curve curve = (wall.Location as LocationCurve).Curve;
				if (curve as Arc != null)
				{
					this.m_vec = this.m_Wall.Orientation;
				}
				else
				{
					this.m_vec = this.m_Wall.Orientation;
				}
				this.ProfileLine = CommonInterface.GetXYPlaneCurve(curve);
			}
			this.AnalyzesWall();
		}

		public bool TryMegerMultichannelWall(WallDataEx otherWallDataEx)
		{
			try
			{
				if (!this.IsMultichannelWall(otherWallDataEx))
				{
					return false;
				}
				if (otherWallDataEx.m_bOutWall)
				{
					this.m_bOutWall = otherWallDataEx.m_bOutWall;
					this.VecOutWall = otherWallDataEx.VecOutWall;
					this.WallId = otherWallDataEx.WallId;
					this.ProfileLine = otherWallDataEx.ProfileLine;
				}
				List<Curve> list = new List<Curve>();
				if (Geometry.LessThan(this.m_WallMinWidth, this.m_Wall.Width))
				{
					list.Add(this.InLine);
					list.Add(this.OutLine);
				}
				if (Geometry.LessThan(this.m_WallMinWidth, otherWallDataEx.m_Wall.Width))
				{
					list.Add(otherWallDataEx.InLine);
					list.Add(otherWallDataEx.OutLine);
				}
				if (list.Count > 1)
				{
					List<XYZ> list2 = GeometryHelper.LineWithLstCvIntersect(Line.CreateUnbound((this.InLine.GetEndPoint(0) + this.InLine.GetEndPoint(1)) / 2.0, this.VecOutWall), list);
					list2.Sort(new PointSort());
					XYZ xyz = list2[0];
					XYZ xyz2 = list2[list2.Count - 1];
					if ((xyz2 - xyz).Normalize().IsAlmostEqualTo(this.VecOutWall))
					{
						XYZ xyz3 = xyz2;
						xyz2 = xyz;
						xyz = xyz3;
					}
					foreach (Curve curve in list)
					{
						if (GeometryHelper.Is_Point_OnSegment(curve, xyz))
						{
							this.OutLine = curve;
						}
						else if (GeometryHelper.Is_Point_OnSegment(curve, xyz2))
						{
							this.InLine = curve;
						}
					}
					this.m_lstWallWindows.AddRange(otherWallDataEx.m_lstWallWindows);
					return true;
				}
			}
			catch
			{
				return false;
			}
			return true;
		}

		private bool IsMultichannelWall(WallDataEx otherWallDataEx)
		{
			try
			{
				if (!this.VecOutWall.IsAlmostEqualTo(otherWallDataEx.VecOutWall) && !this.VecOutWall.IsAlmostEqualTo(-otherWallDataEx.VecOutWall))
				{
					return false;
				}
				double num = this.InLine.Length - otherWallDataEx.InLine.Length;
				num = ((num > 0.0) ? num : (-num));
				if (Geometry.LessThan(this.m_dTolerance, num))
				{
					return false;
				}
				Line line = Line.CreateUnbound((this.InLine.GetEndPoint(0) + this.InLine.GetEndPoint(1)) / 2.0, this.VecOutWall);
				IntersectionResultArray intersectionResultArray;
                if ((int)otherWallDataEx.InLine.Intersect(line, out intersectionResultArray) != 8 || intersectionResultArray == null || intersectionResultArray.IsEmpty)
				{
					return false;
				}
				if (Geometry.LessThan(this.GetWallLocationDis(this.m_Wall, otherWallDataEx.m_Wall), this.m_MultichannelWallLength))
				{
					return true;
				}
			}
			catch
			{
				return false;
			}
			return false;
		}

		private double GetWallLocationDis(Wall firstWall, Wall secondWall)
		{
			double result = double.MaxValue;
			try
			{
				Curve curve = (firstWall.Location as LocationCurve).Curve;
				XYZ xyz = (curve.GetEndPoint(0) + curve.GetEndPoint(1)) / 2.0;
				XYZ xyzpoint = (secondWall.Location as LocationCurve).Curve.Project(xyz).XYZPoint;
				result = xyz.DistanceTo(xyzpoint);
			}
			catch
			{
			}
			return result;
		}

		public bool TryCutting2WallInLineAndOutLine(WallDataEx otherWallDataEx)
		{
			try
			{
				Curve curve = null;
				Curve curve2 = null;
				if (GeometryHelper.TryCutting2Curve(this.InLine, otherWallDataEx.InLine, out curve, out curve2) && curve.ApproximateLength - this.InLine.ApproximateLength < this.m_MultichannelWallLength)
				{
					this.InLine = curve;
					otherWallDataEx.InLine = curve2;
				}
				if (GeometryHelper.TryCutting2Curve(this.OutLine, otherWallDataEx.OutLine, out curve, out curve2) && curve.ApproximateLength - this.OutLine.ApproximateLength < this.m_MultichannelWallLength)
				{
					this.OutLine = curve;
					otherWallDataEx.OutLine = curve2;
				}
			}
			catch
			{
				return false;
			}
			return true;
		}

		public void SetDoorWinDataEx(List<DoorWinDataEx> lstDoorWinDataEx)
		{
			this.AnalyzesWall();
			foreach (DoorWinDataEx doorWinDataEx in lstDoorWinDataEx)
			{
				if (doorWinDataEx.hostId.IntegerValue == this.m_wallId.IntegerValue && !doorWinDataEx.bHasHost)
				{
					int integerValue = doorWinDataEx.DWId.IntegerValue;
					XYZ zero = XYZ.Zero;
					if (this.GetProjectPointInCurve(this.InLine, doorWinDataEx.doorWinLine.GetEndPoint(0), out zero) || this.GetProjectPointInCurve(this.InLine, (doorWinDataEx.doorWinLine.GetEndPoint(0) + doorWinDataEx.doorWinLine.GetEndPoint(1)) / 2.0, out zero) || this.GetProjectPointInCurve(this.InLine, doorWinDataEx.doorWinLine.GetEndPoint(1), out zero))
					{
						this.m_lstWallWindows.Add(doorWinDataEx);
						doorWinDataEx.bHasHost = true;
					}
				}
			}
		}

		private bool GetProjectPointInCurve(Curve cv, XYZ pt, out XYZ ptNew)
		{
			ptNew = XYZ.Zero;
			try
			{
				if (cv is Line)
				{
					Line line = cv as Line;
					ptNew = line.Project(pt).XYZPoint;
					if (Geometry.IsEqual((pt - ptNew).Normalize().DotProduct(line.Direction.Normalize()), 0.0))
					{
						return true;
					}
					return false;
				}
				else if (cv is Arc)
				{
					Arc arc = cv as Arc;
					Line line2 = Line.CreateBound(arc.Center, pt + (pt - arc.Center).Normalize() * Common.MMToFeet(10000.0));
					IntersectionResultArray intersectionResultArray;
                    if ((int)arc.Intersect(line2, out intersectionResultArray) != 8 || intersectionResultArray == null || intersectionResultArray.IsEmpty)
					{
						return false;
					}
					return true;
				}
			}
			catch
			{
				return false;
			}
			return false;
		}

		private void AnalyzesWall()
		{
			if (this.m_bIsAnalyzed)
			{
				return;
			}
			this.m_bIsAnalyzed = true;
			if (this.m_Wall == null)
			{
				return;
			}
			this.GetWallStructLine(this.m_Wall, ref this.m_inLine, ref this.m_outLine);
		}

		private bool GetWallStructLine(Wall wall, ref Curve structInCv, ref Curve structOutCv)
		{
			double num = 0.0;
			double num2 = 0.0;
			CompoundStructure compoundStructure = wall.WallType.GetCompoundStructure();
			if (compoundStructure == null)
			{
				return false;
			}
			IList<CompoundStructureLayer> layers = compoundStructure.GetLayers();
			int firstCoreLayerIndex = compoundStructure.GetFirstCoreLayerIndex();
			int lastCoreLayerIndex = compoundStructure.GetLastCoreLayerIndex();
			for (int i = 0; i < firstCoreLayerIndex; i++)
			{
				CompoundStructureLayer compoundStructureLayer = layers[i];
				num += compoundStructureLayer.Width;
			}
			for (int j = lastCoreLayerIndex + 1; j < layers.Count; j++)
			{
				CompoundStructureLayer compoundStructureLayer2 = layers[j];
				num2 += compoundStructureLayer2.Width;
			}
			Curve xyplaneCurve = CommonInterface.GetXYPlaneCurve((wall.Location as LocationCurve).Curve);
			Line line = xyplaneCurve as Line;
			if (line != null)
			{
				Line line2 = Geometry.OffsetLine(line, wall.Width / 2.0, wall.Orientation);
				structInCv = Geometry.OffsetLine(line2, -num, wall.Orientation);
				line2 = Geometry.OffsetLine(line, wall.Width / 2.0, -wall.Orientation);
				structOutCv = Geometry.OffsetLine(line2, -num2, -wall.Orientation);
			}
			Arc arc = xyplaneCurve as Arc;
			if (arc != null)
			{
				XYZ xyz = arc.Center + wall.Orientation.Normalize() * arc.Radius * 10.0;
				Line line3 = Line.CreateBound(arc.Center, xyz);
				IntersectionResultArray intersectionResultArray;
                if ((int)arc.Intersect(line3, out intersectionResultArray) != 8 || intersectionResultArray == null || intersectionResultArray.IsEmpty)
				{
					double num3 = num;
					num = num2;
					num2 = num3;
				}
				Arc arc2 = Geometry.OffsetArc(wall.Document.Application, arc, wall.Width / 2.0);
				structInCv = Geometry.OffsetArc(wall.Document.Application, arc2, -num);
				arc2 = Geometry.OffsetArc(wall.Document.Application, arc, -wall.Width / 2.0);
				structOutCv = Geometry.OffsetArc(wall.Document.Application, arc2, num2);
			}
			Line.CreateUnbound((xyplaneCurve.GetEndPoint(0) + xyplaneCurve.GetEndPoint(1)) * 0.5, this.m_vec);
			XYZ xyz2 = (structInCv.GetEndPoint(0) + structInCv.GetEndPoint(1)) * 0.5;
			XYZ xyz3 = ((structOutCv.GetEndPoint(0) + structOutCv.GetEndPoint(1)) * 0.5 - xyz2).Normalize();
			if (!this.m_vec.Normalize().IsAlmostEqualTo(xyz3))
			{
				Curve curve = structInCv;
				structInCv = structOutCv;
				structOutCv = curve;
			}
			Curve curve2 = null;
			Curve curve3 = null;
			if (CommonInterface.GetCurveProject(this.m_profileLine, structInCv, out curve2) && CommonInterface.GetCurveProject(this.m_profileLine, structOutCv, out curve3))
			{
				structInCv = curve2;
				structOutCv = curve3;
				return true;
			}
			return false;
		}

		private Wall m_Wall;

		private ElementId m_wallId;

		private bool m_bOutWall;

		private XYZ m_vec;

		private Curve m_profileLine;

		private Curve m_inLine;

		private Curve m_outLine;

		private List<DoorWinDataEx> m_lstWallWindows = new List<DoorWinDataEx>();

		private List<ElementId> m_lstConnectWall = new List<ElementId>();

		private bool m_bIsAnalyzed;

		private double m_MultichannelWallLength = Common.MMToFeet(500.0);

		private double m_WallMinWidth = Common.MMToFeet(150.0);

		private double m_dTolerance = Common.MMToFeet(300.0);
	}
}
